package bb.lanxing.lib.devices.ble.device;

import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

import bb.lanxing.App;
import bb.lanxing.lib.devices.api.SmartDevice;
import bb.lanxing.lib.devices.base.DeviceContext;
import bb.lanxing.lib.devices.base.SimpleBluetoothGattCallbackCompat;
import bb.lanxing.lib.devices.ble.BleCons;
import bb.lanxing.lib.devices.core.ble.AbsBleDevice;
import bb.lanxing.lib.devices.core.provider.DataNotifier;
import bb.lanxing.model.database.Device;
//import bb.lanxing.util.Log;

import java.util.UUID;
import bb.lanxing.lib.devices.ble.BLEAttributes;

public class StandardCadenceDevice extends AbsBleDevice {
    final private static String TAG = "StandardCadenceDevice";
    private int mCSCFeatures;
    public StandardCadenceDevice(SmartDevice smartDevice) {
        super(smartDevice);
    }

    public StandardCadenceDevice(Context context, SmartDevice smartDevice) {
        super(smartDevice);
        init(context, smartDevice.getAddress(), new CadenceGattCallback(this));
    }

    public StandardCadenceDevice(Context context, SmartDevice smartDevice, BluetoothGattCallback btGattCallback) {
        super(smartDevice);
        init(context, smartDevice.getAddress(), btGattCallback);
    }

    @Override
    public void onServicesDiscovered() {
        final BluetoothGattService service = this.mBluetoothGatt.getService(UUID.fromString(BLEAttributes.BLE_CADENCE_SERVICE));
        if (service != null) {
            Log.d(TAG, "onServicesDiscovered...");
            setCharacteristicNotification(service.getCharacteristic(UUID.fromString(BLEAttributes.BLE_CADENCE_MEASUREMENT)), true);
            getHandler().postDelayed(() ->
                    readCharacteristic(service.getCharacteristic(UUID.fromString(BLEAttributes.BLE_CADENCE_CSC_FEATURE))), 1400L);
        }
    }


    public void updateCSCFeature(int cscValue) {
        this.mCSCFeatures = cscValue;
        SmartDevice device = getDevice();
        Log.d(TAG,"updateCSCFeature mCSCFeatures=" + mCSCFeatures);
        device.setFlags(cscValue);
        ((Device) device).setUserId(App.getContext().getUserId());//no userId in new device object
        DeviceContext.save(device);
        Context applicationContext = DeviceContext.getApplicationContext();
        if (applicationContext != null) {
            Intent intent = new Intent("ACTION_DEVICE_INFORMATION");
            intent.putExtra("EXTRA_DEVICE_TYPE", getType());
            intent.putExtra("EXTRA_CSC_FUTURE", cscValue);
            intent.putExtra("EXTRA_DEVICE_ADDRESS", getAddress());
            intent.setPackage(applicationContext.getPackageName());
            applicationContext.sendBroadcast(intent);
        }
    }

//    public void updateBatteryLevel(int batteryValue) {
//        Log.d(TAG,"updateBatteryLevel: batteryValue=" + batteryValue);
//        Context applicationContext = DeviceContext.getApplicationContext();
//        if (applicationContext != null) {
//            Intent intent = new Intent(BleCons.ACTION_BATTERY);
//            intent.putExtra("EXTRA_DEVICE_TYPE", getType());
//            intent.putExtra("EXTRA_BATTERY", batteryValue);
////            intent.putExtra("EXTRA_DEVICE_ADDRESS", getAddress());
//            intent.setPackage(applicationContext.getPackageName());
//            applicationContext.sendBroadcast(intent);
//        }
//    }

    protected static class CadenceGattCallback extends SimpleBluetoothGattCallbackCompat<StandardCadenceDevice> {
        public CadenceGattCallback(StandardCadenceDevice standardCadenceDevice) {
            super(standardCadenceDevice);
        }

        @Override
        public void onCharacteristicRead(BluetoothGatt bluetoothGatt, BluetoothGattCharacteristic btGattCharacter, int i) {
            super.onCharacteristicRead(bluetoothGatt, btGattCharacter, i);
            UUID vUuid = btGattCharacter.getUuid();
            if (UUID.fromString(BLEAttributes.BLE_CADENCE_CSC_FEATURE).equals(vUuid)) {
                int cscValue = btGattCharacter.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0);
                this.mClientRef.updateCSCFeature(cscValue);
                Log.d(TAG, "onCharacteristicRead: CSCFeatures cscValue=" + cscValue);
            }
//            else if (UUID.fromString(BLEAttributes.BLE_BATTERY_CHARACTERISTIC).equals(vUuid)) {
//                int batteryValue = btGattCharacter.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0);
//                this.mClientRef.updateBatteryLevel(batteryValue);
//                Log.d(TAG,"onCharacteristicRead: batteryValue=" + batteryValue);
//            }
        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt btGatt, BluetoothGattCharacteristic btGattCharacter) {
            int vSumWheel = -1;
            int vWheelTime = -1;
            int vCadenceTime = -1;
            int vSumCadence = -1;
            int vTemperature = -1;
            int vPressure = -1;

            super.onCharacteristicChanged(btGatt, btGattCharacter);
            if (UUID.fromString(BLEAttributes.BLE_CADENCE_CSC_FEATURE).equals(btGattCharacter.getUuid())) {
                int cscValue = btGattCharacter.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0);
                if(this.mClientRef.mCSCFeatures != cscValue) {
                    this.mClientRef.updateCSCFeature(cscValue);
                    Log.d(TAG,"CSCFeatures: " + cscValue);
                }
            }

            int type = this.mClientRef.getType();
            if (UUID.fromString(BLEAttributes.BLE_CADENCE_MEASUREMENT).equals(btGattCharacter.getUuid())) {
                int measureValue = btGattCharacter.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0);
                int vOffset = 1;
                if ((measureValue & 1) > 0) {
                    vSumWheel = btGattCharacter.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT32, vOffset);
                    vOffset += 4;
                    vWheelTime = btGattCharacter.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, vOffset);
                    vOffset += 2;
                }

                if ((measureValue & 2) > 0) {
                    vSumCadence = btGattCharacter.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, vOffset);
                    vOffset += 2;
                    vCadenceTime = btGattCharacter.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, vOffset);
                    vOffset += 2;
                }

                if ((measureValue & 4) > 0) {
                    vPressure = btGattCharacter.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT32, vOffset);
                    vOffset += 4;
                    vTemperature = btGattCharacter.getIntValue(BluetoothGattCharacteristic.FORMAT_SINT16, vOffset);
                }

                if (vSumWheel != -1 || vWheelTime != -1) {
                    DataNotifier.notifyRawSpeedCadenceData(type, vWheelTime, vSumWheel);
                }
                if (vSumCadence != -1 || vCadenceTime != -1) {
                    DataNotifier.notifyRawCadenceData(type, vCadenceTime, vSumCadence);
                }
                if (vPressure != -1) {
                    DataNotifier.notifyPressureData(type, vPressure);
                }
                if (vTemperature != -1) {
                    DataNotifier.notifyTemperatureData(type, vTemperature);
                }
                Log.d(TAG,"onCadenceData: sumWheel = " + vSumWheel + ", wheelTime = " + vWheelTime
                        + ", sumCadence = " + vSumCadence + ", cadenceTime = " + vCadenceTime
                        + ", pressure = " + vPressure + ", temperature = " + vTemperature);
            }
        }
    }
}
